package cn.cdiothree.service.impl;

import cn.cdiothree.DTO.CartDTO;
import cn.cdiothree.DTO.OrderDTO;
import cn.cdiothree.converter.ProductOrder2OrderDTOConverter;
import cn.cdiothree.dao.OrderItemMapper;
import cn.cdiothree.dataobject.OrderItem;
import cn.cdiothree.dataobject.ProductInfo;
import cn.cdiothree.dataobject.ProductOrder;
import cn.cdiothree.dao.ProductOrderMapper;
import cn.cdiothree.enums.OrderStatusEnum;
import cn.cdiothree.enums.PayStatusEnum;
import cn.cdiothree.enums.ResultEnum;
import cn.cdiothree.exception.SellException;
import cn.cdiothree.service.ProductInfoService;
import cn.cdiothree.service.ProductOrderService;
import cn.cdiothree.util.KeyUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author CumThing
 * @since 2020-02-02
 */
@Service
@Slf4j
public class ProductOrderServiceImpl extends ServiceImpl<ProductOrderMapper,ProductOrder> implements ProductOrderService {

    @Autowired
    private ProductInfoService productInfoService;

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private ProductOrderMapper productOrderMapper;

    /**
     * 创建订单
     * @param orderDTO
     * @return
     */
    @Override
    @Transactional
    public OrderDTO create(OrderDTO orderDTO) {
        log.info("用户{}创建新订单",orderDTO.getUserId());
        String orderId=KeyUtil.genUniqueKey();
        BigDecimal orderAmount=new BigDecimal(BigInteger.ZERO);
//        List<CartDTO> cartDTOList=new ArrayList<>();
        //1.查询商品（数量，价格）
        for (OrderItem orderItem:orderDTO.getOrderItemList()){
            ProductInfo productInfo=productInfoService.findById(orderItem.getId());
            if (productInfo==null){
                throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
            }
            //2.计算订单总价
            orderAmount=productInfo.getProductPrice().
                    multiply(new BigDecimal(orderItem.getQuantity()))
                    .add(orderAmount);
            //订单详情入库
            orderItem.setItemId(KeyUtil.genUniqueKey());
            orderItem.setOrderId(orderId);
            BeanUtils.copyProperties(productInfo,orderItem);
            orderItem.setCreateTime(LocalDateTime.now());
            orderItem.setUpdateTime(LocalDateTime.now());

            orderItemMapper.insert(orderItem);

//            CartDTO cartDTO=new CartDTO(orderItem.getId(),orderItem.getQuantity());
//            cartDTOList.add(cartDTO);
        }

        //3.写入订单数据库（productOrder和orderItem）
        ProductOrder productOrder = new ProductOrder();
        orderDTO.setOrderId(orderId);
        BeanUtils.copyProperties(orderDTO,productOrder);
        productOrder.setOrderId(orderId);
        productOrder.setOrderAmount(orderAmount);
        productOrder.setOrderStatus(OrderStatusEnum.NEW.getCode());
        productOrder.setPayStatus(PayStatusEnum.WAIT.getCode());
//        BeanUtilseanUtils.copyProperties(orderDTO,productOrder);
        productOrderMapper.insert(productOrder);
        //4.扣库存
        List<CartDTO> cartDTOList=orderDTO.getOrderItemList().stream().map(e ->
                new CartDTO(e.getId(),e.getQuantity())
        ).collect(Collectors.toList());
        productInfoService.decreaseStock(cartDTOList);
        return orderDTO;
    }


    /**
     * 查找订单
     * @param orderId
     * @return
     */
    @Override
    public OrderDTO findOne(String orderId) {
        log.info("查找订单{}详情",orderId);
//        QueryWrapper<ProductOrder> productOrderQueryWrapper=new QueryWrapper<>();
//        productOrderQueryWrapper.eq("orderId",orderId);
        ProductOrder productOrder=productOrderMapper.selectById(orderId);
        if (productOrder==null){
            throw new SellException(ResultEnum.ORDER_NOT_EXIST);
        }

        List<OrderItem> orderItemList=orderItemMapper.findByOrderId(orderId);
        if (CollectionUtils.isEmpty(orderItemList)){
            throw new SellException(ResultEnum.ORDERDETAIL_NOT_EXIST);
        }

        OrderDTO orderDTO=new OrderDTO();
        BeanUtils.copyProperties(productOrder,orderDTO);
        orderDTO.setOrderItemList(orderItemList);
        return orderDTO;
    }

    /**
     * 根据用户id查找订单列表
     * @param num
     * @param size
     * @param userId
     * @return
     */
    @Override
    public PageInfo<OrderDTO> findList(int num, int size, Integer userId) {
        log.info("用户{}查找订单列表",userId);
        QueryWrapper<ProductOrder> productOrderQueryWrapper=new QueryWrapper<>();
        productOrderQueryWrapper.eq("user_id",userId);
        PageHelper.startPage(num,size);
        List<ProductOrder> productOrderList=productOrderMapper.selectList(productOrderQueryWrapper);
        List<OrderDTO> orderDTOList=ProductOrder2OrderDTOConverter.convert(productOrderList);
//        for (OrderDTO orderDTO:orderDTOList){
//            List<OrderItem> orderItemList = orderItemMapper.findByOrderId(orderDTO.getOrderId());
//            orderDTO.setOrderItemList(orderItemList);
//        }
        for (int i = 0;i<orderDTOList.size();i++){
            List<OrderItem> orderItemList = orderItemMapper.findByOrderId(orderDTOList.get(i).getOrderId());
            orderDTOList.get(i).setOrderItemList(orderItemList);
        }
        PageInfo<OrderDTO> orderDTOPageInfo=new PageInfo<OrderDTO>(orderDTOList);
        return orderDTOPageInfo;
    }

    /**
     * 取消订单
     * @param orderDTO
     * @return
     */
    @Override
    @Transactional
    public OrderDTO cancel(OrderDTO orderDTO) {
        ProductOrder productOrder =new ProductOrder();

        //判断订单状态
        if(!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
            log.error("【取消订单】订单状态不正确，orderId={},orderStatus={}",orderDTO.getOrderId(),orderDTO.getOrderStatus());
            throw new  SellException(ResultEnum.ORDER_STATUS_ERROR);
        }
        //修改订单状态
        orderDTO.setOrderStatus(OrderStatusEnum.CANEL.getCode());
        BeanUtils.copyProperties(orderDTO,productOrder);
        //TODO
        int updateResult=productOrderMapper.updateById(productOrder);
        if (updateResult==0){
            log.error("【取消订单】更新失败，orderMaster={}",productOrder);
            throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
        }
        //返还库存
        if (CollectionUtils.isEmpty(orderDTO.getOrderItemList())){
            log.error("【取消订单】订单中无商品详情，orderDTO={}",orderDTO);
            throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY);
        }
        List<CartDTO> cartDTOList=orderDTO.getOrderItemList().stream()
                .map(e ->new CartDTO(e.getId(),e.getQuantity()))
                .collect(Collectors.toList());
        productInfoService.increaseStock(cartDTOList);
        //如果已经支付，需要退款
        if (orderDTO.getPayStatus().equals(PayStatusEnum.SUCCESS.getCode())){
            //TODO
        }
        return orderDTO;
    }

    /**
     * 完结订单
     * @param orderDTO
     * @return
     */
    @Override
    @Transactional
    public OrderDTO finish(OrderDTO orderDTO) {
        //判断订单状态
        if (!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
            log.error("【完结订单】订单状态不正确，orderId={},orderStatus",orderDTO.getOrderId(),orderDTO.getOrderStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }
        //修改订单状态
        orderDTO.setOrderStatus(OrderStatusEnum.FINISHED.getCode());
        ProductOrder productOrder=new ProductOrder();
        BeanUtils.copyProperties(orderDTO,productOrder);
        //TODO
        int updateResult=productOrderMapper.updateById(productOrder);
        if (updateResult==0){
            log.error("【完结订单】更新失败，orderMaster={}",productOrder);
            throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
        }
        return orderDTO;
    }


    /**
     * 修改订单支付状态
     * @param orderDTO
     * @return
     */
    @Override
    @Transactional
    public OrderDTO paid(OrderDTO orderDTO) {
        //判断订单状态
        if (!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
            log.error("【订单支付成功】订单状态不正确，orderId={},orderStatus",orderDTO.getOrderId(),orderDTO.getOrderStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }
        //判断支付状态
        if (!orderDTO.getPayStatus().equals(PayStatusEnum.WAIT.getCode())){
            log.error("【订单支付完成】订单支付状态不正确,orderDTO={}",orderDTO);
            throw new SellException(ResultEnum.ORDER_PAY_STATUS_ERROR);
        }
        //修改支付状态
        orderDTO.setPayStatus(PayStatusEnum.SUCCESS.getCode());
        ProductOrder productOrder=new ProductOrder();
        BeanUtils.copyProperties(orderDTO,productOrder);
        //TODO
        int updateResult=productOrderMapper.updateById(productOrder);
        if (updateResult==0){
            log.error("【订单支付完成】更新失败，orderMaster={}",productOrder);
            throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
        }

        return orderDTO;
    }


    /**
     * 查看订单列表
     * @param num
     * @param size
     * @return
     */
    @Override
    public PageInfo<OrderDTO> findList(int num, int size) {
        QueryWrapper<ProductOrder> productOrderQueryWrapper=new QueryWrapper<>();
        PageHelper.startPage(num,size);
        List<ProductOrder> productOrderList=productOrderMapper.selectList(productOrderQueryWrapper);
        List<OrderDTO> orderDTOList=ProductOrder2OrderDTOConverter.convert(productOrderList);
        PageInfo<OrderDTO> orderDTOPageInfo=new PageInfo<OrderDTO>(orderDTOList);
        return orderDTOPageInfo;
    }
}
